package emulator.hardware.clock;

import java.util.Observer;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class BarrierClock implements Clock
{
	private TickScales _tickScales = new TickScales();
	private int _cntClocks = 0;
	private CyclicBarrier _barrier = null;
	private long _systemTicks;
	
	public void startClock()
	{
		_barrier = new CyclicBarrier(_cntClocks);
		_tickScales.init();
		_systemTicks = 0;
	}

	@Override
	public ClockHandle acquireHandle()
	{
		if (_barrier != null)
			return null;
		return new BarrierClockHandle(this, ++_cntClocks);
	}

	@Override
	public void releaseHandle(ClockHandle handle)
	{
		_barrier = null;
		_cntClocks--;
	}

	@Override
	public void addClockSpeedObserver(Observer clockSpeedObserver)
	{
		_tickScales.addObserver(clockSpeedObserver);
	}
	
	void tick(int id) throws InterruptedException, BrokenBarrierException
	{
		_barrier.await();
		_systemTicks ++;
		if ((_systemTicks % 1000) == 0)
			_tickScales.measureTicks(_systemTicks);
	}

	public long getFrequency()
	{
		return _tickScales.getClockSpeed();
	}
}
